#!/bin/sh
#
# Copyright (c) 2009-2010,2012-2013,2018 LAAS/CNRS
# All rights reserved.
#
# Redistribution and use  in source  and binary  forms,  with or without
# modification, are permitted provided that the following conditions are
# met:
#
#   1. Redistributions of  source  code must retain the  above copyright
#      notice, this list of conditions and the following disclaimer.
#   2. Redistributions in binary form must reproduce the above copyright
#      notice,  this list of  conditions and the following disclaimer in
#      the  documentation  and/or  other   materials provided  with  the
#      distribution.
#
# THIS  SOFTWARE IS PROVIDED BY  THE  COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND  ANY  EXPRESS OR IMPLIED  WARRANTIES,  INCLUDING,  BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR  PURPOSE ARE DISCLAIMED. IN  NO EVENT SHALL THE COPYRIGHT
# HOLDERS OR      CONTRIBUTORS  BE LIABLE FOR   ANY    DIRECT, INDIRECT,
# INCIDENTAL,  SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE   OF THIS SOFTWARE, EVEN   IF ADVISED OF   THE POSSIBILITY OF SUCH
# DAMAGE.
#
#                                      Anthony Mallet on Fri Jan  9 2009
#

# --------------------------------------------------------------------------
#
# NAME
#	checkout -- checkout a reposityory, regardless of format
#
# SYNOPSIS
#	checkout [options] repository [file ...]
#
# DESCRIPTION
#	checkout will checkout the contents of the named repository into the
#	the current working directory.  If any optional files are specified
#	then only they will be extracted from the repository, provided that the
#	underlying tool supports this ability.
#
# OPTIONS
#	-f format	Specify the repository format, by default git. Valid
#			formats are: git, cvs, svn, dir.
#
#	-r revision	Checkout this revision instead of HEAD. The syntax of
#			revision depends on the underlying checkout tool.
#
#	-d dir		Extract the files into the specified dir instead
#			of the current working directory.  If the directory
#			doesn't exist, then it is created along with any
#			intermediate directories using the current umask.
#
#
# ENVIRONMENT
#	CHECKOUT_VCS_OPTS
#		This variable set additional arguments passed to the
#		actualy checkout command (cvs checkout, git clone or svn checkout).
#
# --------------------------------------------------------------------------

set -e		# exit on errors
set -u		# treat undefined variables as errors

: ${TEST:=test}
: ${ECHO:=echo}
: ${FIND:=find}
: ${LN:=ln}
: ${MKDIR:=mkdir -p}
: ${GIT:=git}
: ${CVS:=cvs}
: ${SVN:=svn}

: ${TMPDIR:=/tmp}
: ${CHECKOUT_VCS_OPTS=}

self="${0##*/}"

usage() {
	${ECHO} 1>&2 "usage: $self [-f format] [-r revision] [-d dir] repository [file ...]"
}

extract_dir=
revision=
format=git

# Process optional arguments
while ${TEST} $# -gt 0; do
	case "$1" in
	-f)	format="$2"; shift 2 ;;
	-r)	revision="$2"; shift 2 ;;
	-d)	extract_dir="$2"; shift 2 ;;
	--)	shift; break ;;
	-?*)	${ECHO} 1>&2 "$self: unknown option -- ${1#-}"
		usage
		exit 1
		;;
	*)	break ;;
	esac
done

# Process required arguments
${TEST} $# -gt 0 || { usage; exit 1; }
repository="$1"; shift


# Use the correct tool and extraction procedure to perform the checkout
# based on the repository format.
#
case "$format" in
git)
    if ${TEST} -d "$extract_dir"; then
        ${GIT} -C "$extract_dir" pull -v ${CHECKOUT_VCS_OPTS} $repository
    else
        ${GIT} clone -v ${CHECKOUT_VCS_OPTS} $repository $extract_dir
    fi
    if ${TEST} -n "$revision"; then
        ${GIT} -C "$extract_dir" checkout $revision
    fi
    ;;

cvs)
    : ${_revision=}
    : ${_extract_dir=}
    : ${cwd=`pwd`}
    ${TEST} -n "$revision" && _revision="-r $revision"
    ${TEST} -n "$extract_dir" && _extract_dir="-d ${extract_dir##${cwd%/}/}"
    ${CVS} -d $repository checkout \
	${CHECKOUT_VCS_OPTS} $_revision $_extract_dir ${1+"$@"}
    ;;

svn)
    : ${_revision=}
    : ${_extract_dir=}
    : ${cwd=`pwd`}
    ${TEST} -n "$revision" && _revision="-r $revision"
    ${TEST} -n "$extract_dir" && _extract_dir="${extract_dir##${cwd%/}/}"
    ${SVN} --non-interactive --trust-server-cert checkout \
	 ${CHECKOUT_VCS_OPTS} $_revision $repository $_extract_dir ${1+"$@"}
    ;;

dir)
    : ${sub=.}
    ${TEST} -n "${1+$1}" && sub="$1"
    ${TEST} -n "$extract_dir" || {
        ${ECHO} 1>&2 "$self: no extract dir defined: use -d."; exit 2
    }
    ${TEST} -d "$extract_dir" || ${MKDIR} "$extract_dir"

    # remove any broken link
    ${FIND} "$extract_dir" -type l \! -exec ${TEST} -e {} \; -delete

    # mirror directory tree
    { cd "$repository" && ${FIND} "$sub" -type d; } |
      { cd "$extract_dir" && while read d; do ${MKDIR} "$d"; done; }
    { cd "$repository" && ${FIND} "$sub" ! -type d; } |
      { cd "$extract_dir" && while read d;
          do ${LN} -sf "$repository/$d" "$d";
        done; }
    ;;
esac

exit 0
